module VirtualCity.Scripts.Bus

open Casanova
open Casanova.Utilities
open Casanova.Core
open Casanova.Coroutines
open Casanova.Game
open Casanova.Input
open Casanova.Math
open Casanova.Drawing
open VirtualCity.City
open VirtualCity.CityDescription

/// Buses loop in the following manner:
/// - they go to the next stop
/// - they load/unload passengers
let rec do_rounds(bus:Bus,city:City) = 
  let clock = city.Clock
  let update_passenger_positions =
    co{
      for p in !bus.Passengers do
        (!p.Agent).Physical.Position := !bus.Physics.Position
        (!p.Agent).Physical.Target   := !bus.Physics.Position
      do! yield_
    } |> repeat_
  co{
    for s in bus.Stops do
      do bus.Physics.Target := s.Location
      do! wait_condition(fun () -> Vector2<m>.Distance(!bus.Physics.Target, s.Location) < 0.1f<m>) .||> update_passenger_positions
      do! wait_condition(fun () -> !clock.Time >= s.Time) .||> update_passenger_positions
      let passengers = !bus.Passengers
      do bus.Passengers := 
            [
              for p in passengers do 
                if !p.Destination <> s then
                  yield p
              for w in !s.BusWaiters do
                if w.BusNumber = bus.Number then
                  yield  {
                          Agent       = w.Agent
                          Destination = w.Destination
                        }
            ]
      let bus_waiters = !s.BusWaiters
      do s.BusWaiters := 
            [
              for w in bus_waiters do
                if w.BusNumber <> bus.Number then
                  yield w
            ]
    let time = !city.Clock.Time // wait for tomorrow
    do! wait_condition(fun () -> time > !clock.Time)
    return! do_rounds(bus,city)
  }
